// request.js
import axios from "axios"; //引入 axios
// import Vue from "vue";
import qs from "qs"; // 引入qs模块，用来序列化post类型的数据，某些请求会用得到
import { Toast, Notify } from "vant"; //引入Toast 模块，用于信息提示
import store from "@/store"; //引入 vuex 中的数据

// // 环境的切换
if (process.env.NODE_ENV === "development") {
  //本地测试
  axios.defaults.baseURL = "http://121.36.139.116:2411";
} else if (process.env.NODE_ENV === "test") {
  //测试环境
  axios.defaults.baseURL = "";
} else if (process.env.NODE_ENV === "production") {
  //生产环境
  axios.defaults.baseURL = "http://www.shanqi111.cn/v1.0";
}

// 用于存储目前状态为pending的请求标识信息
let pendingRequest = [];

//创建axios实例
const service = axios.create({
  // baseURL: process.env.BASE_API,
  timeout: 5000, // request timeout  设置请求超时时间
  responseType: "json",
  withCredentials: false, // 是否允许带cookie这些,部分项目开启可能出现跨域问题
  headers: {
    "Content-Type": "application/json;charset=utf-8"
  }
});

// 请求拦截器
service.interceptors.request.use(
  config => {
    // 在发送请求之前做什么
    if (config.method === "post") {
      // 序列化
      // config.data = qs.stringify(config.data);
      // config.data = JSON.stringify(config.data);
      // 提示,若是能直接接受json 格式,可以不用 qs 来序列化的
      config.headers["Content-Type"] =
        "application/x-www-form-urlencoded;charset=UTF-8";
    } else {
      if (store.getters.token) {
        // 若是有做鉴权token , 就给头部带上token
        // 让每个请求携带token-- ['X-Token']为自定义key 请根据实际情况自行修改
        // 若是需要跨站点,存放到 cookie 会好一点,限制也没那么多,有些浏览环境限制了 localstorage (隐身模式)的使用
        // config.headers['X-Token'] = getToken()
      }
    }

    // 区别请求的唯一标识，这里用方法名+请求路径
    // 如果一个项目里有多个不同baseURL的请求
    // 可以改成`${config.method} ${config.baseURL}${config.url}`
    const requestMark = `${config.method} ${config.url}`;
    // 找当前请求的标识是否存在pendingRequest中，即是否重复请求了
    const markIndex = pendingRequest.findIndex(item => {
      return item.name === requestMark;
    });
    // 存在，即重复了
    if (markIndex > -1) {
      // 取消上个重复的请求
      pendingRequest[markIndex].cancel();
      // 删掉在pendingRequest中的请求标识
      pendingRequest.splice(markIndex, 1);
    }
    // （重新）新建针对这次请求的axios的cancelToken标识
    const CancelToken = axios.CancelToken;
    const source = CancelToken.source();
    config.cancelToken = source.token;
    // 设置自定义配置requestMark项，主要用于响应拦截中
    config.requestMark = requestMark;
    // 记录本次请求的标识
    pendingRequest.push({
      name: requestMark,
      cancel: source.cancel,
      routeChangeCancel: config.routeChangeCancel // 可能会有优先级高于默认设置的routeChangeCancel项值
    });

    return config;
  },
  error => {
    // 对请求错误做些什么，自己定义
    Notify({ type: "danger", message: "error" });
    // Message({                  //使用element-ui的message进行信息提示
    //   showClose: true,
    //   message: error,
    //   type: "warning"
    // });
    return Promise.reject(error);
  }
);

// 响应拦截器
service.interceptors.response.use(
  response => {
    // 如果返回的状态码为200，说明接口请求成功，可以正常拿到数据
    // 否则的话抛出错误
    if (response.status === 200) {
      // 根据请求拦截里设置的requestMark配置来寻找对应pendingRequest里对应的请求标识
      const markIndex = pendingRequest.findIndex(item => {
        return item.name === response.requestMark;
      });
      // 找到了就删除该标识
      markIndex > -1 && pendingRequest.splice(markIndex, 1);
      return Promise.resolve(response);
    } else {
      return Promise.reject(response);
    }
  },
  // 服务器状态码不是2开头的的情况
  // 跟后台开发人员协商好统一的错误状态码
  // 然后根据返回的状态码进行一些操作，例如登录过期提示，错误提示等等
  error => {
    // if (error.response.status) {
    //   switch (error.response.status) {
    //     // 401: 未登录
    //     // 未登录则跳转登录页面，并携带当前页面的路径
    //     // 在登录成功后返回当前页面，这一步需要在登录页操作。
    //     // case 401:
    //     //     router.replace({
    //     //         path: '/login',
    //     //         query: {
    //     //             redirect: router.currentRoute.fullPath
    //     //         }
    //     //     });
    //     //     break;
    //     // 403 token过期
    //     // 登录过期对用户进行提示
    //     // 清除本地token和清空vuex中token对象
    //     // 跳转登录页面
    //     // case 403:
    //     //       Message({
    //     //         message: '登录过期，请重新登录',
    //     //         duration: 1000,
    //     //         forbidClick: true
    //     //     });
    //     //     // 清除token
    //     //     localStorage.removeItem('token');
    //     //     store.commit('loginSuccess', null);
    //     //     // 跳转登录页面，并将要浏览的页面fullPath传过去，登录成功后跳转需要访问的页面
    //     //     setTimeout(() => {
    //     //         router.replace({
    //     //             path: '/login',
    //     //             query: {
    //     //                 redirect: router.currentRoute.fullPath
    //     //             }
    //     //         });
    //     //     }, 1000);
    //     //     break;
    //     // 404请求不存在
    //     case 404:
    //       Notify({ type: "danger", message: "网络请求不存在" });
    //       // Message({
    //       //     message: '网络请求不存在',
    //       //     duration: 1500,
    //       //     forbidClick: true
    //       // });
    //       break;
    //     // 其他错误，直接抛出错误提示
    //     default:
    //       Notify({ type: "danger", message: error.response.data.resp_message });
    //     // Message({
    //     //     message: error.response.data.message,
    //     //     duration: 1500,
    //     //     forbidClick: true
    //     // });
    //   }

    let errorFormat = {};
    const response = error.response;
    // 请求已发出，但服务器响应的状态码不在 2xx 范围内
    if (response) {
      // 根据请求拦截里设置的requestMark配置来寻找对应pendingRequest里对应的请求标识
      const markIndex = pendingRequest.findIndex(item => {
        return item.name === error.requestMark;
      });
      // 找到了就删除该标识
      markIndex > -1 && pendingRequest.splice(markIndex, 1);

      errorFormat = {
        status: response.status,
        data: response.data
      };
    }
    // 如果是主动取消了请求，做个标识
    if (axios.isCancel(error)) {
      errorFormat.selfCancel = true;
    }
    // 其实还有一个情况
    // 在设置引发错误的请求时，error.message才是错误信息
    // 但我觉得这个一般是脚本错误，我们项目提示也不应该提示脚本错误给用户看，一般都是我们自定义一些默认错误提示，如“创建成功！”
    // 所以这里不针对此情况做处理。

    return Promise.reject(errorFormat);
    // return Promise.reject(error.response);
    // }
  }
);

// 默认把请求视为切换路由就会把pending状态的请求取消，false为不取消
service.defaults.routeChangeCancel = true;

export default service;
